<template lang="pug">
  el-row(type="flex" align="middle")
    el-col(:span="10")
      el-card.dataWrapper(shadow="never" :body-style="{padding: 0}")
        h3(slot="header" class="header")
          el-checkbox(:indeterminate="leftObj.isIndeterminate" v-model="leftObj.checkAll" @change="val => handleCheckAllChange(val, 'left')" v-if="!queryFn" :disabled="disabled")
            | {{titles[0]}}
          span(v-else) {{titles[0]}}
        el-input.el-transfer-panel__filter(placeholder="请输入" v-model="leftObj.searchVal" :disabled="disabled")
          i(
            class="el-icon-search el-input__icon"
            slot="suffix"
            @click="searchHandle"
          )
        .infinite-list-wrapper(
          style="overflow:auto;height: 200px"
          v-infinite-scroll="getList"
          :infinite-scroll-disabled="!queryFn || leftObj.page === leftObj.pages"
          )
          el-checkbox-group.checkList(
            v-model="leftObj.ids"
            @change="value => handleCheckedChange(value, 'left')"
            :disabled="disabled"
          )
            el-checkbox.block(v-for="item in listFilters(leftObj.list, leftObj.searchVal, !!queryFn)" :key="item[prop.id]" :label="item[prop.id]") {{item[prop.label]}}
          p.tc.f12(v-if="leftObj.loading && queryFn") 加载中...
          p.tc.c_secondary.mb10.f12(v-if="leftObj.total === leftObj.list.length && !leftObj.loading  && queryFn") 没有更多了
    el-col.tc(:span="4")
      el-button.mb10(type="primary" circle icon="el-icon-arrow-right" :disabled="leftObj.ids.length === 0" @click="selectHandle")
      br
      el-button(type="primary" circle icon="el-icon-arrow-left" :disabled="rightObj.ids.length === 0" @click="cancelHandle")
    el-col(:span="10")
      el-card.dataWrapper(shadow="never" :body-style="{padding: 0}")
        h3(slot="header" class="header")
          el-checkbox(:indeterminate="rightObj.isIndeterminate" v-model="rightObj.checkAll" @change="val => handleCheckAllChange(val, 'right')" :disabled="disabled")
            | {{titles[1]}}
        el-input.el-transfer-panel__filter(placeholder="请输入" v-model="rightObj.searchVal" :disabled="disabled")
          i(
            class="el-icon-search el-input__icon"
            slot="suffix"
          )
        .infinite-list-wrapper(style="overflow:auto;height: 200px")
          el-checkbox-group.checkList(v-model="rightObj.ids" @change="value => handleCheckedChange(value, 'right')" :disabled="disabled")
            el-checkbox.block(v-for="item in listFilters(rightObj.list, rightObj.searchVal)" :key="item[prop.id]" :label="item[prop.id]") {{item[prop.label]}}
</template>
<script>
export default {
  props: {
    dataSource: {
      type: Array,
      default: () => []
    },
    selectIds: {
      type: Array,
      default: () => []
    },
    queryFn: {
      type: Function,
      default: null
    },
    titles: {
      type: Array,
      default: () => ['列表1', '列表2']
    },
    prop: {
      type: Object,
      default: () => {
        return { id: 'id', label: 'label' }
      }
    },
    disabled: {
      type: Boolean,
      default: false
    },
    searchKey: {
      type: String,
      default: 'name'
    },
    change: {
      type: Function,
      default: null
    }
  },
  watch: {
    'rightObj.list' (val) {
      const { change } = this
      if (change) {
        change(val)
      }
    },
    dataSource (val) {
      const { prop: { id } } = this
      this.leftObj.list = val
      this.leftObj.checkAll = false
      this.leftObj.ids = []
      // 在已选择列表中筛选出移除了的待选项
      const ids = val.map(x => {
        return x[id]
      })
      this.rightObj.list = this.rightObj.list.filter(x => ids.includes(x[id]))
      this.rightObj.ids = []
      this.rightObj.checkAll = false
    }
  },
  data () {
    return {
      leftObj: {
        loading: false,
        isIndeterminate: false,
        checkAll: false,
        list: this.dataSource,
        searchVal: '',
        page: 0,
        pages: 1,
        total: 0,
        pageSize: 20,
        ids: this.selectIds // 选中id集合
      },
      rightObj: {
        isIndeterminate: false,
        checkAll: false,
        list: [], // 全部列表
        searchVal: '',
        ids: [] // 选中id集合
      }
    }
  },
  created () {
    // this.getList()
  },
  methods: {
    getList (pageNum) {
      const { queryFn, searchKey, leftObj: { page, pageSize, searchVal, list } } = this
      if (!queryFn) {
        return
      }
      this.leftObj.loading = true
      queryFn({ pageNum: pageNum || page + 1, pageSize }, { [searchKey]: searchVal }).then(res => {
        this.leftObj = {
          ...this.leftObj,
          total: res.recordCounts,
          page: res.pageNum,
          pages: res.pages,
          list: [...list, ...res.data]
        }
      }).finally(() => {
        this.leftObj.loading = false
      })
    },
    // 选择， 判断是否全选
    handleCheckedChange (val, type) {
      const list = this[type + 'Obj'].list // 待选项
      const checkedCount = val.length // 选中项有几条
      this[type + 'Obj'].checkAll = checkedCount === list.length
      this[type + 'Obj'].isIndeterminate = checkedCount > 0 && checkedCount < list.length
    },
    // 全选
    handleCheckAllChange (val, type) {
      const ids = this[type + 'Obj'].list.map(x => {
        return x[this.prop.id]
      })
      this[type + 'Obj'].ids = val ? ids : []
      this[type + 'Obj'].isIndeterminate = false
    },
    // 左边选中项添加到右边
    selectHandle () {
      const { leftObj: { list, ids, page, pages }, prop } = this
      // 右边列表添加已经选中的项
      const choseList = list.filter(x => ids.includes(x[prop.id]))
      // 左边列表剔除已经选中的项
      this.leftObj.list = list.filter(x => !ids.includes(x[prop.id]))
      this.leftObj = { ...this.leftObj }
      this.rightObj = {
        ...this.rightObj,
        list: [...this.rightObj.list, ...choseList]
      }
      this.leftObj.ids = []
      this.leftObj.checkAll = false
      if (page < pages) {
        this.getList()
      }
    },
    // 取消右侧选中项
    cancelHandle () {
      const { rightObj: { list, ids }, prop } = this
      const choseList = list.filter(x => ids.includes(x[prop.id]))
      this.rightObj.list = list.filter(x => !ids.includes(x[prop.id]))
      this.rightObj = { ...this.rightObj }
      this.leftObj = {
        ...this.leftObj,
        list: [...this.leftObj.list, ...choseList]
      }
      this.rightObj.ids = []
      this.rightObj.checkAll = false
    },
    // flag 直接返回list，不进行删选, 当queryFn传入方法了，则直接返回list
    listFilters (list, val, flag) {
      if (flag) {
        return list
      }
      const { prop: { label } } = this
      return list.filter(x => x[label].includes(val))
    },
    // 搜索
    searchHandle () {
      const { queryFn } = this
      // 传入加载方法后才进行删选
      if (!queryFn) {
        return
      }
      this.leftObj.list = []
      this.getList(1)
    }
  }
}
</script>
<style lang="scss" scoped>
.dataWrapper{
  border: 1px solid $--border-color-lighter;

  /deep/ .el-card__header{
    padding: 0;
  }

  .header {
    padding: 0 15px;
    background: $--color-background2;
    height: 40px;
    line-height: 40px;
    font-size: 14px;
    font-weight: normal;
  }
}

.checkList{
  label {
    padding: 0 15px;
    line-height: 30px;
    height: 30px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
}
</style>
